﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
//using System.Web.Security;

namespace WPay.Infrastructure.Unity
{
    /// <summary>
    /// 加密/解密类
    /// 加密：Encrypt
    /// 解密：Decrypt
    /// 参考资料：https://www.cnblogs.com/kissdodog/p/3386068.html
    /// </summary>
    public class DESEncrypt
    {
        /// <summary>
        /// PDA注册密钥 加密/解密使用
        /// </summary>
        public const string PublicKey = "AwEAAci0Agcbsxrb3UUtDRu8JXlKd79Johns3Fsm4JFbWwRfGsF/iinN7yUPwoQUdetJfeJtM3wuT07oBSA2+mSSNDclrDtA6YwCllu/ZCnxMR7EaucGmOIEg2qocqM8M+lL8xVlkY+/HZkXMegHZeAeyqwp7t+r24T81O67sNMqZT4R";
        /*
        .NET Framework 提供以下实现私钥加密算法的类：
            DES：DESCryptoServiceProvider 
            RC2：RC2CryptoServiceProvider 
            Rijndael（AES）：RijndaelManaged 
            3DES：TripleDESCryptoServiceProvider
          
        .NET Framework 提供以下实现公钥加密算法的类： 
            DSA：DSACryptoServiceProvider 
            RSA：RSACryptoServiceProvider  
          
        .NET Framework 提供以下实现数字签名算法的类： 
            HMAC：HMACSHA1 （HMAC 为一种使用密钥的 Hash 算法） 
            MAC：MACTripleDES 
            MD5：MD5CryptoServiceProvider 
            SHA1：SHA1Managed、SHA256Managed、SHA384Managed、SHA512Managed
         */
        /// <summary>
        /// 默认密钥
        /// </summary>
        private const string sKeyDefa = "qJzGEh6hESZDVJeCnFPGuxzaiB7NLQM3";
        /// <summary>
        /// 默认矢量 IV
        /// </summary>
        private const string sIVDefa = "Rkb4jvUy/ye7Cd7k89QQgQ==";
        #region 单向散列算法

        #region MD5加密
        /// <summary>
        /// MD5加密摘要算法
        /// Author:HFL
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByMD5(string encryptStr)
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
                using (var md5 = MD5.Create())
                {
                    var result = md5.ComputeHash(Encoding.ASCII.GetBytes(encryptStr));
                    var md5Str = BitConverter.ToString(result);
                    return md5Str.Replace("-", "");
                }
#pragma warning disable 618
            //string md5Str = MD5.Create().ComputeHash(); FormsAuthentication.HashPasswordForStoringInConfigFile(encryptStr, "md5");
#pragma warning restore 618
            //return md5Str.Length > 0 ? md5Str : "";
        }
        /// <summary>
        /// MD5加密摘要算法
        /// Author:HFL
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByMD5_WinForm(string encryptStr)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] fromData = System.Text.Encoding.UTF8.GetBytes(encryptStr);
            byte[] targetData = md5.ComputeHash(fromData);
            string md5Str = null;

            for (int i = 0; i < targetData.Length; i++)
            {
                md5Str += targetData[i].ToString("x2");
            }
            if (string.IsNullOrEmpty(md5Str))
                return "";
            return md5Str.ToUpper();
        }

        /// <summary>
        /// MD5两次加密
        /// Author:HFL
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="isDouble">是否两次加密</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByMD5(string encryptStr, bool isDouble)
        {
            string md5Dbl = isDouble ? EncryptByMD5(EncryptByMD5(encryptStr).ToUpper()) : EncryptByMD5(encryptStr);
            return md5Dbl;
        }
        /// <summary>
        /// MD5两次加密，并截取掉后几位
        /// Author:HFL
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="isDouble">是否两次加密</param>
        /// <param name="length">需要截取的长度</param>
        /// <returns></returns>
        public static string EncryptByMD5(string encryptStr, bool isDouble, int length)
        {
            string md5Dbl = EncryptByMD5(encryptStr, isDouble);
            if (length > 31 || length < 0)
                return md5Dbl;
            return md5Dbl.Length > 0 ? md5Dbl.Substring(0, md5Dbl.Length - length) : "";
        }
        #endregion MD5

        #region SHA 加密  说明： 这是一种较新的散列算法，可以对任意长度的数据运算生成一个160位的数值
        /// <summary>
        /// SHA数字签名
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptBySHA(string encryptStr)
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
//#pragma warning disable 618
//            string shaStr = FormsAuthentication.HashPasswordForStoringInConfigFile(encryptStr, "SHA1");
//#pragma warning restore 618
//            return shaStr.Length > 0 ? shaStr : "";

            SHA1 sha1 = SHA1.Create();
            byte[] hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(encryptStr));
            string shaStr = BitConverter.ToString(hash);
            shaStr = shaStr.Replace("-", "");
            return shaStr;
        }
        #endregion SHA

        #region SHA1加密/验证  说明： 这是一种较新的散列算法，可以对任意长度的数据运算生成一个160位的数值
        /// <summary>
        /// SHA1数字签名
        /// </summary>
        /// <param name="plaintext">原文</param>
        /// <param name="privateKey">私钥</param>
        /// <returns>签名</returns>
        public static string EncryptBySHA1(string plaintext, string privateKey)
        {
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] dataToEncrypt = ByteConverter.GetBytes(plaintext);

            using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
            {
                RSAalg.FromXmlString(privateKey);
                //使用SHA1进行摘要算法，生成签名
                byte[] encryptedData = RSAalg.SignData(dataToEncrypt, new SHA1CryptoServiceProvider());
                return Convert.ToBase64String(encryptedData);
            }
        }
        /// <summary>
        /// SHA256数字签名
        /// </summary>
        /// <param name="plaintext">原文</param>
        /// <param name="privateKey">私钥</param>
        /// <returns>签名</returns>
        public static string EncryptBySHA256(string plaintext)
        {
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] dataToEncrypt = ByteConverter.GetBytes(plaintext);
            SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider();
            byte[] byteArr = sha256.ComputeHash(dataToEncrypt);
            return BitConverter.ToString(byteArr);

            //using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
            //{
            //    RSAalg.FromXmlString(privateKey);
            //    //使用SHA256进行摘要算法，生成签名
            //    byte[] encryptedData = RSAalg.SignData(dataToEncrypt, new SHA256CryptoServiceProvider());
            //    return Convert.ToBase64String(encryptedData);
            //}
        }

        /// <summary>
        /// 验证签名
        /// </summary>
        /// <param name="plaintext">原文</param>
        /// <param name="SignedData">签名</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static bool CheckSign(string plaintext, string SignedData, string publicKey)
        {
            using (RSACryptoServiceProvider RSAalg = new RSACryptoServiceProvider())
            {
                RSAalg.FromXmlString(publicKey);
                UnicodeEncoding ByteConverter = new UnicodeEncoding();
                byte[] dataToVerifyBytes = ByteConverter.GetBytes(plaintext);
                byte[] signedDataBytes = Convert.FromBase64String(SignedData);
                return RSAalg.VerifyData(dataToVerifyBytes, new SHA1CryptoServiceProvider(), signedDataBytes);
            }
        }
        #endregion SHA1

        #region 账户加密

        /// <summary>
        /// 生成加密字
        /// [调用示例：string keyWord = DESEncrypt.EncrptKeyWord("0001","0001","000100304");]
        /// </summary>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        public static string EncrptKeyWord(string keyH, params object[] keyWord)
        {
            return EncrptKeyWordByAlg(null, keyH, keyWord);
        }

        /// <summary>
        /// 验证加密字
        /// [调用示例：bool isPass = DESEncrypt.CheckKeyWord("A239FS934J42372JF90L23","0001","000100304");]
        /// </summary>
        /// <param name="keyWordString">源加密字</param>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        public static bool CheckKeyWord(string keyWordString, string keyH, params object[] keyWord)
        {
            //获取算法编码
            //string alg = keyWordString.Substring(keyWordString.Length - 1, 1);
            string alg = keyWordString.Substring(4, 1);
            //根据算法编码，请求对应加密算法，获取加密字
            string tmpKeyWord = EncrptKeyWordByAlg(alg, keyH, keyWord);

            //判断校验字是否一致
            if (keyWordString == tmpKeyWord)
                return true;
            return false;
        }
        /// <summary>
        /// 随机生成签名算法代码
        /// </summary>
        /// <returns></returns>
        private static string RandomAlg()
        {
            string randomChars = "A";//支持的算法代码ABCD
            string alg = string.Empty;
            Random random = new Random();
            //随机产生算法
            int randomNum = random.Next(randomChars.Length);
            alg += randomChars[randomNum];
            return alg;
        }
        /// <summary>
        /// 生成加密字
        /// [调用示例：string keyWord = DESEncrypt.EncrptKeyWord(out alg,"0001","0001","000100304");]
        /// </summary>
        /// <param name="alg">算法代码【可空，空则随机】</param>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        private static string EncrptKeyWordByAlg(string alg, string keyH, params object[] keyWord)
        {
            //随机生成签名算法代码
            if (string.IsNullOrWhiteSpace(alg))
                alg = RandomAlg();
            //根据算法编码，请求对应加密算法，获取加密字
            string tmpKeyWord = string.Empty;
            switch (alg)
            {
                case "A":
                    tmpKeyWord = EncrptKeyWord_A(keyH, keyWord);
                    break;
                case "B":
                    tmpKeyWord = EncrptKeyWord_B(keyH, keyWord);
                    break;
                case "C":
                    tmpKeyWord = EncrptKeyWord_C(keyH, keyWord);
                    break;
                case "D":
                    tmpKeyWord = EncrptKeyWord_D(keyH, keyWord);
                    break;
            }
            tmpKeyWord=tmpKeyWord.Insert(4, alg);
           //在加密字中，加入算法代码
           //tmpKeyWord += alg;
            return tmpKeyWord;
        }
        /// <summary>
        /// 加密算法A【私有方法】
        /// [调用示例：string keyWord = EncrptKeyWord_A("0001","0001","000100304");]
        /// </summary>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        private static string EncrptKeyWord_A(string keyH, params object[] keyWord)
        {
            //按参数排序后，进行加密
            List<object> d = keyWord.ToList();
            d.Sort();
            string dStr = string.Join(",", d);
            dStr = EncryptByMD5(keyH + dStr, true);
            return dStr;
        }

        /// <summary>
        /// 加密算法B【私有方法】
        /// [调用示例：string keyWord = EncrptKeyWord_B("0001","0001","000100304");]
        /// </summary>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        private static string EncrptKeyWord_B(string keyH, params object[] keyWord)
        {
            //按参数排序后，进行加密
            return null;
            //List<object> d = keyWord.ToList();
            //d.Sort();
            //string dStr = string.Join(",", d);
            //dStr = EncryptByMD5(keyH + dStr, true);
            //return dStr;
        }

        /// <summary>
        /// 加密算法C【私有方法】
        /// [调用示例：string keyWord = EncrptKeyWord_C("0001","0001","000100304");]
        /// </summary>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        private static string EncrptKeyWord_C(string keyH, params object[] keyWord)
        {
            return null;
            //按传入顺序进行加密
            //string dStr = string.Join(",", keyWord);
            ////一次MD5加密
            //dStr = EncryptByMD5(keyH + dStr);
            //return dStr;
        }
        /// <summary>
        /// 加密算法D【私有方法】
        /// [调用示例：string keyWord = EncrptKeyWord_D("0001","0001","000100304");]
        /// </summary>
        /// <param name="keyH">算法头信息</param>
        /// <param name="keyWord">数据源</param>
        /// <returns></returns>
        private static string EncrptKeyWord_D(string keyH, params object[] keyWord)
        {
            return null;
            //按参数排序后，进行加密
            //List<object> d = keyWord.ToList();
            //d.Sort();
            //string dStr = string.Join(",", d);
            ////一次MD5加密
            //dStr = EncryptByMD5(keyH + dStr);
            //return dStr;
        }


        #endregion

        #endregion 单向散列算法

        /// <summary>
        /// Base64加密【标准编码方式】
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns></returns>
        public static string EncryptBase64(string encryptStr)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(encryptStr);
            return Convert.ToBase64String(bytes);
        }
        /// <summary>
        /// Base64解密【标准编码方式】
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <returns></returns>
        public static string DecryptBase64(string decryptStr)
        {
            byte[] bytes = Convert.FromBase64String(decryptStr);
            return Encoding.UTF8.GetString(bytes);
        }

        /// <summary>
        /// Base64加密【非标准编码方式】
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="encoding">编码格式，默认传null或不传，默认UTF-8编码</param>
        /// <returns></returns>
        public static string EncryptByBase64(string encryptStr, string sKey = "", System.Text.Encoding encoding = null)
        {
            string base64Key = sKey;
            char[] Base64Code = new char[]{'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
         'U','V','W','X','Y','Z','0','a','1','b','2','c','3','d','4','e','5','f','6','g','7','h','8','i','9','j','k','l','m','n',
         'o','p','q','r','s','t','u','v','w','x','y','z','+','/','='};
            if (!string.IsNullOrEmpty(base64Key))
            {
                List<char> base64CodeList = Base64Code.ToList<char>();
                List<char> base64KeyList = base64Key.ToList<char>();
                //将Base64Code中与base64Key中相同字符移除，并将此字符添加到Base64Code最前面
                for (int i = base64KeyList.Count - 1; i >= 0; i--)
                {
                    base64CodeList.Remove(base64KeyList[i]);
                    base64CodeList.Insert(0, base64KeyList[i]);
                }
                Base64Code = base64CodeList.ToArray<char>();
            }
            //将需要加密的字符串转换为byte数组
            byte empty = (byte)0;
            byte[] by;
            if (encoding == null)
                by = System.Text.Encoding.UTF8.GetBytes(encryptStr);
            else
                by = encoding.GetBytes(encryptStr);
            //将转换后的byte数组转换为数组集合
            System.Collections.ArrayList byteMessage = new System.Collections.ArrayList(by);
            System.Text.StringBuilder outmessage;
            int messageLen = byteMessage.Count;
            //将字符分成3个字节一组，如果不足，则以0补齐
            int page = messageLen / 3;
            int use = 0;
            if ((use = messageLen % 3) > 0)
            {
                for (int i = 0; i < 3 - use; i++)
                    byteMessage.Add(empty);
                page++;
            }
            //将3个字节的每组字符转换成4个字节一组的。3个一组，一组一组变成4个字节一组
            //方法是：转换成ASCII码，按顺序排列24位数据，再把这24位数据分成4组，即每组6位。
            //再在每组的的最高位前补两个0凑足一个字节。
            outmessage = new System.Text.StringBuilder(page * 4);
            for (int i = 0; i < page; i++)
            {
                //取一组3个字节的组
                byte[] instr = new byte[3];
                instr[0] = (byte)byteMessage[i * 3];
                instr[1] = (byte)byteMessage[i * 3 + 1];
                instr[2] = (byte)byteMessage[i * 3 + 2];
                //六个位为一组，补0变成4个字节 
                int[] outstr = new int[4];
                //第一个输出字节：取第一输入字节的前6位，并且在高位补0，使其变成8位（一个字节） 
                outstr[0] = instr[0] >> 2;
                //第二个输出字节：取第一输入字节的后2位和第二个输入字节的前4位（共6位），并且在高位补0，使其变成8位（一个字节） 
                outstr[1] = ((instr[0] & 0x03) << 4) ^ (instr[1] >> 4);
                //第三个输出字节：取第二输入字节的后4位和第三个输入字节的前2位（共6位），并且在高位补0，使其变成8位（一个字节）
                if (!instr[1].Equals(empty))
                    outstr[2] = ((instr[1] & 0x0f) << 2) ^ (instr[2] >> 6);
                else
                    outstr[2] = 64;
                //第四个输出字节：取第三输入字节的后6位，并且在高位补0，使其变成8位（一个字节） 
                if (!instr[2].Equals(empty))
                    outstr[3] = (instr[2] & 0x3f);
                else
                    outstr[3] = 64;
                outmessage.Append(Base64Code[outstr[0]]);
                outmessage.Append(Base64Code[outstr[1]]);
                outmessage.Append(Base64Code[outstr[2]]);
                outmessage.Append(Base64Code[outstr[3]]);
            }
            return outmessage.ToString();
        }

        /// <summary>
        /// Base64解密【非标准编码方式】
        /// </summary>
        /// <param name="encryptStr">需要解密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="encoding">编码格式，默认传null或不传，默认UTF-8编码</param>
        /// <returns></returns>
        public static string DecryptByBase64(string decryptStr, string sKey = "", System.Text.Encoding encoding = null)
        {
            if ((decryptStr.Length % 4) != 0)
            {
                throw new ArgumentException("不是正确的BASE64编码，请检查。", "Message");
            }
            if (!System.Text.RegularExpressions.Regex.IsMatch(decryptStr, "^[A-Z0-9/+=]*$", System.Text.RegularExpressions.RegexOptions.IgnoreCase))
            {
                throw new ArgumentException("包含不正确的BASE64编码，请检查。", "Message");
            }

            string base64Key = sKey;
            string Base64Code = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz+/=";

            if (!string.IsNullOrEmpty(base64Key))
            {
                List<char> base64CodeList = Base64Code.ToList<char>();
                List<char> base64KeyList = base64Key.ToList<char>();
                //将Base64Code中与base64Key中相同字符移除，并将此字符添加到Base64Code最前面
                for (int i = base64KeyList.Count - 1; i >= 0; i--)
                {
                    base64CodeList.Remove(base64KeyList[i]);
                    base64CodeList.Insert(0, base64KeyList[i]);
                }
                Base64Code = string.Join("", base64CodeList);
            }

            int page = decryptStr.Length / 4;
            System.Collections.ArrayList outMessage = new System.Collections.ArrayList(page * 3);
            char[] message = decryptStr.ToCharArray();
            for (int i = 0; i < page; i++)
            {
                byte[] instr = new byte[4];
                instr[0] = (byte)Base64Code.IndexOf(message[i * 4]);
                instr[1] = (byte)Base64Code.IndexOf(message[i * 4 + 1]);
                instr[2] = (byte)Base64Code.IndexOf(message[i * 4 + 2]);
                instr[3] = (byte)Base64Code.IndexOf(message[i * 4 + 3]);
                byte[] outstr = new byte[3];
                outstr[0] = (byte)((instr[0] << 2) ^ ((instr[1] & 0x30) >> 4));
                if (instr[2] != 64)
                {
                    outstr[1] = (byte)((instr[1] << 4) ^ ((instr[2] & 0x3c) >> 2));
                }
                else
                {
                    outstr[2] = 0;
                }
                if (instr[3] != 64)
                {
                    outstr[2] = (byte)((instr[2] << 6) ^ instr[3]);
                }
                else
                {
                    outstr[2] = 0;
                }
                outMessage.Add(outstr[0]);
                if (outstr[1] != 0)
                    outMessage.Add(outstr[1]);
                if (outstr[2] != 0)
                    outMessage.Add(outstr[2]);
            }
            byte[] outbyte = (byte[])outMessage.ToArray(Type.GetType("System.Byte"));
            //return System.Text.Encoding.Default.GetString(outbyte);
            if (encoding == null)
                return System.Text.Encoding.UTF8.GetString(outbyte);
            else
                return encoding.GetString(outbyte);
        }



        #region DES加密/解密  说明： 对称算法，数据加密标准，速度较快，适用于加密大量数据的场合；
        /// <summary>
        /// DES加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥，且必须为8位</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByDES(string encryptStr, string sKey = null)
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa.Substring(0, 8);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptStr);
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                string str = Convert.ToBase64String(ms.ToArray());
                ms.Close();
                if (!string.IsNullOrEmpty(str))
                    str = str.Replace("+", "%2B");
                return str;
            }
        }

        /// <summary>
        /// DES解密
        /// </summary>
        /// <param name="decryptStr">要解密的字符串</param>
        /// <param name="sKey">密钥，且必须为8位</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByDES(string decryptStr, string sKey = null)
        {
            if (string.IsNullOrEmpty(decryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa.Substring(0, 8);
            decryptStr = decryptStr.Replace("%2B", "+");
            byte[] inputByteArray = Convert.FromBase64String(decryptStr);
            using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
            {
                des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
                des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
                System.IO.MemoryStream ms = new System.IO.MemoryStream();
                using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(inputByteArray, 0, inputByteArray.Length);
                    cs.FlushFinalBlock();
                    cs.Close();
                }
                string str = Encoding.UTF8.GetString(ms.ToArray());
                ms.Close();
                return str;
            }
        }
        #endregion

        #region 3DES加密/解密  说明： 是基于DES的对称算法，对一块数据用三个不同的密钥进行三次加密，强度更高；

        /// <summary>
        /// 3DES加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByTripleDES(string encryptStr, string sKey = "")
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
            MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();
            DES.Key = hashMD5.ComputeHash(Encoding.Default.GetBytes(sKey));
            DES.Mode = CipherMode.ECB;
            ICryptoTransform DESEncrypt = DES.CreateEncryptor();
            byte[] Buffer = Encoding.Default.GetBytes(encryptStr);
            return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
        }
        /// <summary>
        /// 3DES解密
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByTripleDES(string decryptStr, string sKey = "")
        {
            if (string.IsNullOrEmpty(decryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();
            MD5CryptoServiceProvider hashMD5 = new MD5CryptoServiceProvider();

            DES.Key = hashMD5.ComputeHash(Encoding.Default.GetBytes(sKey));
            DES.Mode = CipherMode.ECB;
            ICryptoTransform DESDecrypt = DES.CreateDecryptor();
            string result = "";
            try
            {
                byte[] Buffer = Convert.FromBase64String(decryptStr);
                result = Encoding.Default.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
            }
            catch (System.Exception)
            {
                //throw (new System.Exception("null", e));
                return "";
            }
            return result;
        }

        //构造一个对称算法
        private static SymmetricAlgorithm mCSP = new TripleDESCryptoServiceProvider();
        /// <summary>
        /// 3DES加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="sIV">矢量</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByTripleDES(string encryptStr, string sKey, string sIV)
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;
            //密钥的生成可以用mCSP.GenerateKey（）来生成，矢量的生成也可以用mCSP.GenerateIV()来生成。
            //mCSP.GenerateKey();
            //mCSP.GenerateIV();
            mCSP.Key = Convert.FromBase64String(sKey);
            mCSP.IV = Convert.FromBase64String(sIV);
            //指定加密的运算模式
            mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
            //获取或设置加密算法的填充模式
            mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
            ct = mCSP.CreateEncryptor(mCSP.Key, mCSP.IV);
            byt = Encoding.UTF8.GetBytes(encryptStr);
            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return Convert.ToBase64String(ms.ToArray());
        }

        /// <summary>
        /// 3DES解密
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="sIV">矢量</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByTripleDES(string decryptStr, string sKey, string sIV)
        {
            if (string.IsNullOrEmpty(decryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;
            //密钥的生成可以用mCSP.GenerateKey（）来生成，矢量的生成也可以用mCSP.GenerateIV()来生成。
            //mCSP.GenerateKey();
            //mCSP.GenerateIV();
            mCSP.Key = Convert.FromBase64String(sKey);
            mCSP.IV = Convert.FromBase64String(sIV);

            mCSP.Mode = System.Security.Cryptography.CipherMode.ECB;
            mCSP.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
            ct = mCSP.CreateDecryptor(mCSP.Key, mCSP.IV);
            byt = Convert.FromBase64String(decryptStr);
            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();
            return Encoding.UTF8.GetString(ms.ToArray());
        }
        #endregion

        #region RC2和RC4 加密/解密  说明：对称算法，用变长密钥对大量数据进行加密，比 DES 快；
        /// <summary>
        /// RC2加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥(必须为5-16位)</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByRC2(string encryptStr, string sKey = "")
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa.Length >= 16 ? sKeyDefa.Substring(0, 16) : sKeyDefa.Substring(0, 5);
            string returnValue;
            try
            {
                byte[] temp = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                RC2CryptoServiceProvider rC2 = new RC2CryptoServiceProvider();
                byte[] byteEncryptString = Encoding.Default.GetBytes(encryptStr);
                MemoryStream memorystream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memorystream, rC2.CreateEncryptor(Encoding.Default.GetBytes(sKey), temp), CryptoStreamMode.Write);
                cryptoStream.Write(byteEncryptString, 0, byteEncryptString.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Convert.ToBase64String(memorystream.ToArray());
            }
            catch (Exception)
            {
                return "";
            }
            return returnValue;
        }

        /// <summary>
        /// RC2解密
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <param name="sKey">密钥(必须为5-16位)</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByRC2(string decryptStr, string sKey = "")
        {
            if (string.IsNullOrEmpty(decryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa.Length >= 16 ? sKeyDefa.Substring(0, 16) : sKeyDefa.Substring(0, 5);
            string returnValue;
            try
            {
                byte[] temp = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
                RC2CryptoServiceProvider rC2 = new RC2CryptoServiceProvider();
                byte[] byteDecrytString = Convert.FromBase64String(decryptStr);
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, rC2.CreateDecryptor(Encoding.Default.GetBytes(sKey), temp), CryptoStreamMode.Write);
                cryptoStream.Write(byteDecrytString, 0, byteDecrytString.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Encoding.Default.GetString(memoryStream.ToArray());
            }
            catch (Exception)
            {
                return "";
            }
            return returnValue;
        }

        #endregion



        #region AES 加密/解密  说明：高级加密标准，对称算法，是下一代的加密算法标准，速度快，安全级别高，现在 AES 标准的一个实现是 Rijndael 算法；
        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="sIV">矢量</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByAES(string encryptStr, string sKey = "", string sIV = "")
        {
            if (string.IsNullOrEmpty(encryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            if (string.IsNullOrEmpty(sIV))
                sIV = sIVDefa;
            string returnValue;
            Rijndael AESProvider = Rijndael.Create();
            try
            {
                byte[] byteEncryptString = Encoding.Default.GetBytes(encryptStr);
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, AESProvider.CreateEncryptor(Encoding.Default.GetBytes(sKey), Convert.FromBase64String(sIV)), CryptoStreamMode.Write);
                cryptoStream.Write(byteEncryptString, 0, byteEncryptString.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Convert.ToBase64String(memoryStream.ToArray());
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return returnValue;

        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <param name="sKey">密钥</param>
        /// <param name="sIV">矢量</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByAES(string decryptStr, string sKey = "", string sIV = "")
        {
            if (string.IsNullOrEmpty(decryptStr))
                return "";
            if (string.IsNullOrEmpty(sKey))
                sKey = sKeyDefa;
            if (string.IsNullOrEmpty(sIV))
                sIV = sIVDefa;
            string returnValue = "";
            Rijndael AESProvider = Rijndael.Create();
            try
            {
                byte[] byteDecryptString = Convert.FromBase64String(decryptStr);
                MemoryStream memoryStream = new MemoryStream();
                CryptoStream cryptoStream = new CryptoStream(memoryStream, AESProvider.CreateDecryptor(Encoding.Default.GetBytes(sKey), Convert.FromBase64String(sIV)), CryptoStreamMode.Write);
                cryptoStream.Write(byteDecryptString, 0, byteDecryptString.Length);
                cryptoStream.FlushFinalBlock();
                returnValue = Encoding.Default.GetString(memoryStream.ToArray());
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return returnValue;
        }

        #endregion


        #region RSA 加密/解密  说明：由 RSA 公司发明，是一个支持变长密钥的公共密钥算法，需要加密的文件块的长度也是可变的，非对称算法
        /// <summary>
        /// RSA加密
        /// </summary>
        /// <param name="encryptStr">需要加密的字符串</param>
        /// <returns>返回：已加密的字符串</returns>
        public static string EncryptByRSA(string encryptStr)
        {
            CspParameters csp = new CspParameters();
            csp.KeyContainerName = "rsa";
            RSACryptoServiceProvider RSAProvider = new RSACryptoServiceProvider(csp);
            byte[] encryptBytes = RSAProvider.Encrypt(ASCIIEncoding.ASCII.GetBytes(encryptStr), true);
            string str = "";
            foreach (byte b in encryptBytes)
            {
                str = str + string.Format("{0:x2}", b);
            }
            return str;
        }

        /// <summary>
        /// RSA解密
        /// </summary>
        /// <param name="decryptStr">需要解密的字符串</param>
        /// <returns>返回：已解密的字符串</returns>
        public static string DecryptByRSA(string decryptStr)
        {
            CspParameters csp = new CspParameters();
            csp.KeyContainerName = "rsa";
            RSACryptoServiceProvider RSAProvider = new RSACryptoServiceProvider(csp);
            int length = (decryptStr.Length / 2);
            byte[] decryptBytes = new byte[length];
            for (int index = 0; index < length; index++)
            {
                string substring = decryptStr.Substring(index * 2, 2);
                decryptBytes[index] = Convert.ToByte(substring, 16);
            }
            decryptBytes = RSAProvider.Decrypt(decryptBytes, true);
            return ASCIIEncoding.ASCII.GetString(decryptBytes);
        }

        #endregion



        #region IDEA 加密/解密  说明： 国际数据加密算法，使用 128 位密钥提供非常强的安全性；

        #endregion

        #region DSA 加密/解密  说明：数字签名算法，是一种标准的DSS（数字签名标准），严格来说不算加密算法；

        #endregion

        #region PKCS 加密/解密  说明：(PKCS)是由美国RSA数据安全公司及其合作伙伴制定的一组公钥密码学标准，其中包括证书申请、证书更新、证书作废表发布、扩展证书内容以及数字签名、数字信封的格式等方面的一系列相关协议。
        #endregion

        #region SSF33，SSF28，SCB2(SM1)： 加密/解密  说明：国家密码局的隐蔽不公开的商用算法，在国内民用和商用的，除这些都不容许使用外，其他的都可以使用
        #endregion

        #region 其他算法 ： ElGamal、Diffie-Hellman、新型椭圆曲线算法ECC等
        #endregion

    }
}
